#pragma once

#include <compl.h>


typedef struct mlistnode
{
	struct mlistnode *next;
} mlistnode_t;

typedef struct
{
	mlistnode_t *head;
	sword_t cnt_val;
} mlist_t;

SAI mlistnode_t *mlist_hd_exchg(mlist_t *s, mlistnode_t* new_node){
	return swp(&s->head, new_node);
}

SAI mlistnode_t *mlist_hd_exchg_commit(mlist_t *s, mlistnode_t* new_node){
	return swp_rel(&s->head, new_node);
}

SAI sword_t mlist_addval(mlist_t *s, sword_t val)
{
	return faa(&s->cnt_val, val);
}

SAI sword_t mlist_commit_addval(mlist_t *s, sword_t val){
	return faa_rel(&s->cnt_val, val);
}

SAI void mlist_init(mlist_t *s, sword_t val)
{
	/* 自引用 */
	s->head = (mlistnode_t *)NULL_PTR;
	s->cnt_val = val;
}

#define HC_LOCK_NEXT ((mlistnode_t *)-1)
// fast and slow
SAI void __mlist_push_batch(mlist_t *s, mlistnode_t *hd, mlistnode_t *tl){
	sword_t ret;
	tl->next = HC_LOCK_NEXT;
	mlistnode_t *cur_head = swp_rel(&s->head, hd);
	atm_st(&tl->next, cur_head);
}

SAI sword_t mlist_push_batch(mlist_t *s, mlistnode_t *hd, mlistnode_t *tl, sword_t nr){
	__mlist_push_batch(s, hd, tl);
	/* AARCH64这里是不是直接加比较好? */
	return mlist_addval(s, nr);
}


// SAI sword_t mlist_push_batch(mlist_t *s, mlistnode_t *hd, mlistnode_t *tl, sword_t nr)
// {
// 	sword_t val;
// 	return mlist_push_batch(s, hd, tl, nr);
// }

SAI sword_t mlist_push(mlist_t *s, mlistnode_t *n)
{
	return mlist_push_batch(s, n, n, 1);
}


SAI mlistnode_t *mlist_reclaim_all(mlist_t *s, sword_t val)
{
	sword_t cur_val;
	cur_val = mlist_commit_addval(s,  val);
	// 小于等于都可以放弃
	/* 这里不能并行化 */
	if (cur_val + val <= 0){
		return (mlistnode_t *)NULL_PTR;
	}
	return mlist_hd_exchg(s, (mlistnode_t *)NULL_PTR);
}

// consume
SAI mlistnode_t *mlistnode_consume_head(mlistnode_t *p){
	word_t retry_cnt = 0;
	mlistnode_t *next = p->next;
	return next;
}

// SAI void __mlist_init_list_tail(mlistnode_t **tail, mlistnode_t *hd_sentry){
//	 hd_sentry->next = NULL;
//	 *tail = hd_sentry;
// }

// SAI void __mlist_push_batch_tail_lk(mlistnode_t **tail, mlistnode_t *hd, mlistnode_t *tl){
//	 sword_t ret;
//	 // tl->next = HC_LOCK_NEXT;
//	 tl->next = NULL;
//	 mlistnode_t *prev_tail = fas_r(tail, tl);
//	 //ret = mlist_addval(s, 1);

//	 atm_stl(&prev_tail->next, hd);
	
//	 //tl->next = next;
//	 //return mlist_addval(s, nr);
// }

// SAI sword_t mlist_push_batch_tail_lk(mlistnode_t *s, mlistnode_t *hd, mlistnode_t *tl, sword_t nr){
//	 sword_t ret;
//	 // tl->next = HC_LOCK_NEXT;
//	 tl->next = NULL;
//	 mlistnode_t *prev_tail = fas_r(&s->head, tl);
//	 ret = faa(&s->cnt_val, nr);

//	 atm_stl(&prev_tail->next, hd);
//	 //tl->next = next;
//	 return ret;
//	 //return mlist_addval(s, nr);
// }

